import random, json, conf, OnlineCourseSpider, plan


def createstr(randomlength=16):
    """
    生成一个指定长度的随机字符串
    """
    random_str = ''
    base_str = 'ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789'
    n = len(base_str) - 1
    for i in range(randomlength):
        random_str += base_str[random.randint(0, n)]
    return random_str


def code(cookie):
    if cookie is None:
        cookie = 'token=' + createstr()

    redis_conn = conf.Redis.createcon(conf.Redis, database=0)
    code = json.loads(redis_conn.get('code' + str(random.randint(1, redis_conn.dbsize()))))
    redis_conn.close()

    redis_conn = conf.Redis.createcon(conf.Redis, database=1)
    redis_conn.setex(cookie, conf.Other.codeExpiration, code['auth'])
    redis_conn.close()
    return code['data'], cookie


def login(un, pwd, code, cookie):
    rediscon = conf.Redis.createcon(conf.Redis, database=1)
    pipe = rediscon.pipeline()
    pipe.multi()
    pipe.get(str(cookie))
    pipe.delete(str(cookie))
    rcode = pipe.execute()[0].decode('utf8')
    pipe.close()
    rediscon.close()
    if rcode == code:
        mysqlcon = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
        cu = mysqlcon.cursor()
        cu.execute("select `username` from user where `username`=%s and `password`=%s", (un, pwd))
        res = cu.fetchone()
        cu.close()
        mysqlcon.close()

        if res is not None:
            rediscon = conf.Redis.createcon(conf.Redis, database=2)
            rediscon.setex(str(cookie), conf.Other.cookieExpiration, json.dumps(res))
            rediscon.close()
            return json.dumps({"msg": "登录成功"}), 200
        else:
            return json.dumps({"msg": "用户账号或密码错误"}), 403
    else:
        return json.dumps({"msg": "验证码错误"}), 403


def emailcode(receiver,changepwd=None):
    try:
        redis_conn = conf.Redis.createcon(conf.Redis, database=1)
        code = redis_conn.get(receiver)
        if code is None:
            code = createstr(6)
            redis_conn.setex(receiver, conf.Email.codeExpiration, code)
        else:
            code = code.decode('utf8')
        redis_conn.close()
        import emailsender
        with open('card.html', 'r', encoding='utf8') as f:
            html = f.read().replace('@code@', code)
            if changepwd is not None:
                html = html.replace('欢迎注册', '修改密码')
        emailsender.send(conf.Email.sender, conf.Email.key, receiver, subject="邮箱验证码", body="", html=html)
        resp = json.dumps({"msg": "验证码发送成功,请注意查收"})
    except:
        resp = json.dumps({"msg": "运行时错误"})

    return resp


def register(email,password,phone,verificationCode,invitationCode):
    redis_conn = conf.Redis.createcon(conf.Redis, database=1)
    code = redis_conn.get(email)
    redis_conn.close()
    if code is None or code.decode('utf8') != verificationCode:
        resp = json.dumps({"msg": "验证码错误"})
    else:
        import time
        score, signupdate = '0', time.strftime('%Y-%m-%d %H:%M:%S')
        db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
        cur = db.cursor()
        if invitationCode is not None:
            cur.execute("SELECT `state`,`score` FROM `invitationCode` WHERE `key`=%s", invitationCode)
            res = cur.fetchone()
            if res is not None and res['state'] == '0':
                score = res['score']
        try:
            db.begin()
            cur.execute("INSERT `user` VALUES(%s,%s,%s,%s,%s)",(email,password,phone,signupdate,score))
            if invitationCode is not None:
                cur.execute("UPDATE `invitationCode` set state='1',invitee=%s WHERE `key`=%s", (email,invitationCode))
            db.commit()
            resp = json.dumps({"msg": "注册成功"})
        except:
            db.rollback()
            resp = json.dumps({"msg": "该账户已注册"})
        finally:
            cur.close()
            db.close()

    return resp


def changepwd(email, password, verificationCode):
    print(email, password, verificationCode)
    
    redis_conn = conf.Redis.createcon(conf.Redis, database=1)
    code = redis_conn.get(email)
    redis_conn.close()
    if code is None or code.decode('utf8') != verificationCode:
        resp = json.dumps({"msg": "验证码错误"})
    else:
        try:
            db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
            cur = db.cursor()
            cur.execute("UPDATE `user` SET `password`=%s WHERE username=%s", (password,email))
            db.commit()
            resp = json.dumps({"msg": "修改成功"})
        except:
            resp = json.dumps({"msg": "运行时错误"})
        finally:
            cur.close()
            db.close()
        
    return resp


def Import(url, un, username):
    mysqlcon = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
    cu = mysqlcon.cursor()
    cu.execute("SELECT DISTINCT url FROM `onlineCourseInfo` WHERE un IN (SELECT DISTINCT un FROM `onlineCourseInfo` WHERE url = %s)", url)
    res = cu.fetchall()
    if len(res) > 0:
        for i in range(len(res)):
            res[i]['username'], res[i]['un'], res[i]['pwd'] = username, un, conf.Other.defaultpassword
        cu.executemany("INSERT INTO `onlineCourseInfo` (`username`, `un`, `pwd`, `url`) VALUES (%(username)s, %(un)s, %(pwd)s, %(url)s)", res)
        mysqlcon.commit()
        cu.close()
        mysqlcon.close()
        lst = getlst(res)
        rcon = conf.Redis.createcon(conf.Redis, 3)
        res = rcon.get(username)
        if res is not None:
            for cell in json.loads(res.decode('utf8')):
                lst.append(cell)

        rcon.setex(username, conf.Other.homeListExpiration, json.dumps(lst))
        rcon.close()
        resp = '导入成功（内测功能有未导全可能）'
    else:
        resp = '该校暂不支持此功能'

    return resp


def getlst(lt):
    lst = []
    for cell in lt:
        dct = {'un': cell['un'], 'url': cell['url'], 'pwd': cell['pwd'], 'progress': '', 'name': '密码错误或无时间内课程'}
        spider = OnlineCourseSpider.OnlineCourseSpider(url=cell['url'], un=cell['un'], pwd=cell['pwd'])
        if not spider.login()['status']:
            lst.append(dct.copy())
        else:
            clist = spider.getcourse()
            if clist['status'] and clist['type'] == list and clist['data'] != []:
                for cell in clist['data']:
                    dct['id'] = cell['id']
                    dct['name'] = cell['name']
                    dct['startDate'] = cell['startDate']
                    dct['endDate'] = cell['endDate']
                    dct['progress'] = cell['progress1'][4:-1]
                    lst.append(dct.copy())
            else:
                lst.append(dct.copy())
    return lst


def homelist(username):
    rediscon = conf.Redis.createcon(conf.Redis, 3)
    res = rediscon.get(username)
    if res is not None:
        lst = json.loads(res.decode('utf8'))
    else:
        db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
        cur = db.cursor()
        cur.execute("SELECT `url`,`un`,`pwd` FROM `onlineCourseInfo` WHERE `username`=%s", username)
        res = cur.fetchall()
        cur.close()
        db.close()
        lst = getlst(res)

    rediscon.setex(username, conf.Other.homeListExpiration, json.dumps(lst))
    rediscon.close()

    return lst


def update(username):
    rcon = conf.Redis.createcon(conf.Redis, 3)
    rcon.delete(username)
    rcon.close()


def addUrl(url, un, pwd, username):
    spider = OnlineCourseSpider.OnlineCourseSpider(url, un, pwd)
    res = spider.login()
    if res['status']:
        res = res['data']['result']['data']
        try:
            db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
            cur = db.cursor()
            cur.execute("INSERT onlineCourseInfo VALUES (%s,%s,%s,%s,%s,%s,%s)", (username, un, pwd, url, res['collegeName'], res['className'], res['entryYear']))
            db.commit()
            cur.close()
            db.close()
            lst = getlst([{'url': url, 'un': un, 'pwd': pwd}])
            rcon = conf.Redis.createcon(conf.Redis, 3)
            res = rcon.get(username)
            if res is not None:
                for cell in json.loads(res.decode('utf8')):
                    lst.append(cell)

            rcon.setex(username, conf.Other.homeListExpiration, json.dumps(lst))
            rcon.close()
            return "添加成功"
        except:
            return "运行时错误"
    else:
        return "登录失败，请检查密码是否正确"


def delun(un, username):
    try:
        db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
        cur = db.cursor()
        cur.execute("DELETE FROM onlineCourseInfo WHERE username=%s AND un=%s", (username, un))
        db.commit()
        cur.close()
        db.close()

        rcon = conf.Redis.createcon(conf.Redis, 3)
        res = rcon.get(username)
        lst = []
        if res is not None:
            for cell in json.loads(res.decode('utf8')):
                if cell['un'] != un:
                    lst.append(cell)
        rcon.setex(username, conf.Other.homeListExpiration, json.dumps(lst))
        rcon.close()
        res = "执行成功"
    except:
        res = "执行失败"
    return res


def updatepwd(username, url, un, pwd):
    try:
        db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
        cur = db.cursor()
        cur.execute("UPDATE onlineCourseInfo set `pwd`=%s WHERE `username`=%s AND `un`=%s AND `url`=%s", (pwd, username, un, url))
        db.commit()
        cur.close()
        db.close()

        rcon = conf.Redis.createcon(conf.Redis, 3)
        res = rcon.get(username)
        lst = []
        if res is not None:
            for cell in json.loads(res.decode('utf8')):
                if cell['un'] == un and cell['url'] == url:
                    cell['pwd'] = pwd
                    for dct in getlst([cell]):
                        lst.append(dct)
                else:
                    lst.append(cell)
        rcon.setex(username, conf.Other.homeListExpiration, json.dumps(lst))
        rcon.close()
        res = "更新成功"
    except:
        res = "更新失败"
    return res


def add(url, id, un, pwd, username):
    db = conf.Mysql.createcon(conf.Mysql, conf.Other.datebase)
    cur = db.cursor()
    cur.execute("SELECT `score` FROM `user` WHERE `username`=%s", username)
    score = int(cur.fetchone()['score'])
    if score > 0:
        rcon = conf.Redis.createcon(conf.Redis, 4)
        res = rcon.get("plan")
        lst = [{'url': url, 'id': id, 'un': un, 'pwd': pwd, 'user': username}]
        if res is not None:
            for cell in json.loads(res.decode('utf8')):
                if cell['url'] == url and cell['id'] == id and cell['un'] == un and cell['pwd'] == pwd:
                    if random.randint(0, 5) == 3:
                        rcon.set("notice", 1)
                        plan.check()
                    return "已存在计划中，请勿重复加入"
                lst.append(cell)
        rcon.set("plan", json.dumps(lst))
        rcon.set("notice", 1)
        rcon.close()
        score = str(score - 1)
        cur.execute("UPDATE `user` SET score=%s WHERE username=%s", (score, username))
        db.commit()
        cur.close()
        db.close()
        res = "加入成功,积分剩余:" + score
        plan.check()
    else:
        res = "跳转中"

    return res
